//****************************************************************
//* Copyright (c) 2008 Ford Motor Company. All Rights Reserved.
//*
//* $$Workfile:   CurrencyValuesLogic.java  $$
//* $$Revision:   1.3  $$
//* $$Author:   TMALDON4  $$
//* $$Date:   Dec 15 2008 08:56:56  $$
//*
//*****************************************************************
package ar.com.ford.it.fullEconomics.logic;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Collection;
import ar.com.ford.it.fullEconomics.FullEconomicsPrs;
import ar.com.ford.it.fullEconomics.exception.FullEconomicsException;
import ar.com.ford.it.fullEconomics.persistence.dao.CurrencyValuesDao;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesg01Plant;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesm01Currency;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesm02Currvalue;
import ar.com.ford.it.fullEconomics.util.FullEconomicsDateUtil;
import ar.com.ford.it.fullEconomics.wslx.FullEconomicsWslxUser;
import ar.com.ford.it.webengine.persistence.PersistenceUtil;
import com.ford.it.logging.ILogger;
import com.ford.it.logging.Level;
import com.ford.it.logging.LogFactory;
import com.ford.it.persistence.PersistenceException;

public class CurrencyValuesLogic {

    private static final String CLASS_NAME = CurrencyValuesLogic.class
            .getName();
    private static final ILogger log = LogFactory.getInstance().getLogger(
            CLASS_NAME);

    /**
     * Valida si el rango de fechas es valido, esto es, valida que no exista
     * ningun tipo de cambio en el rango de fechas especificado
     * 
     * @param plant
     * @param codeOrig
     * @param codeDest
     * @param plantfechaIn
     * @param fechaOut
     * @return boolean
     */
    public boolean validRange(Teesg01Plant plant, String codeOrig,
                              String codeDest, String fechaIn, String fechaOut)
            throws FullEconomicsException {

        String METHOD_NAME = "findCurrencyValueByCodes";
        log.entering(CLASS_NAME, METHOD_NAME);

        boolean result;
        Teesm02Currvalue currValue = new Teesm02Currvalue();
        CurrencyLogic currLogic = new CurrencyLogic();
        try {
            Teesm01Currency teesCodeOrigen = currLogic
                    .findCurrencyByCode(codeOrig);
            Teesm01Currency teesCodeDestino = currLogic
                    .findCurrencyByCode(codeDest);

            Calendar fechaInCalendar = FullEconomicsDateUtil.format(fechaIn);
            Timestamp fechaInQuerry = new Timestamp(fechaInCalendar
                    .getTimeInMillis());
            Calendar fechaOutCalendar = FullEconomicsDateUtil.format(fechaOut);
            Timestamp fechaOutQuerry = new Timestamp(fechaOutCalendar
                    .getTimeInMillis());

            currValue.setEesm02PlantCodeC(plant);
            currValue.setEesm02CurrencyValueDateY(fechaInQuerry);
            currValue.setEesm02CurrencyValOutDateY(fechaOutQuerry);
            currValue.setEesm02DestCurrencyCodeC(teesCodeDestino);
            currValue.setEesm02OrigCurrencyCodeC(teesCodeOrigen);
            CurrencyValuesDao currDao = new CurrencyValuesDao();

            result = currDao.validRange(currValue);
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Validate currency Value Range Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.CurrencyValues.INVALIDRANGE);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);

        return result;
    }

    /**
     * Busca Currency Values segun planta, fecha y monedas
     * 
     * @param plant
     * @param fecha
     * @param plantcodeOrigen
     * @param codeDestino
     * @return Currencys que se correspondan con la busqueda.
     */
    public Collection<Teesm02Currvalue> findCurrencieValues(Teesg01Plant plant,
                                                            String fecha,
                                                            String codeOrigen,
                                                            String codeDestino)
            throws FullEconomicsException {

        String METHOD_NAME = "findCurrencieValues";
        log.entering(CLASS_NAME, METHOD_NAME);

        CurrencyValuesDao dao = new CurrencyValuesDao();
        CurrencyLogic currLogic = new CurrencyLogic();
        Teesm02Currvalue currencyValue = new Teesm02Currvalue();
        Collection<Teesm02Currvalue> ret = null;
        Teesm01Currency teesCodeOrigen = currLogic
                .findCurrencyByCode(codeOrigen);
        Teesm01Currency teesCodeDestino = currLogic
                .findCurrencyByCode(codeDestino);

        // si no se especifica una fecha, busco los tipos de cambio actuales        
        Calendar fechaCalendar = null;
        Timestamp fechaQuerry = null;
        if (fecha != null) {
            fechaCalendar = FullEconomicsDateUtil.format(fecha);
        }
        if (fechaCalendar != null)
            fechaQuerry = new Timestamp(fechaCalendar.getTimeInMillis());
        else
            fechaQuerry = new Timestamp(System.currentTimeMillis());
        currencyValue.setEesm02OrigCurrencyCodeC(teesCodeOrigen);
        currencyValue.setEesm02DestCurrencyCodeC(teesCodeDestino);
        currencyValue.setEesm02PlantCodeC(plant);
        try {
            ret = dao.findCurrencyValues(currencyValue, fechaQuerry);
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Find Currencies Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.CurrencyValues.FINDALL);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);

        return ret;
    }

    
    
    
    public Collection<Teesm02Currvalue> findCurrencieValues(Teesg01Plant plant,
                                                            Timestamp fecha,
                                                            Teesm01Currency teesCodeOrigen,
                                                            Teesm01Currency teesCodeDestino) throws FullEconomicsException {

    	String METHOD_NAME = "findCurrencieValues";
    	log.entering(CLASS_NAME, METHOD_NAME);

    	CurrencyValuesDao dao = new CurrencyValuesDao();
    	CurrencyLogic currLogic = new CurrencyLogic();
    	Teesm02Currvalue currencyValue = new Teesm02Currvalue();
    	Collection<Teesm02Currvalue> ret = null;
        currencyValue.setEesm02OrigCurrencyCodeC(teesCodeOrigen);
        currencyValue.setEesm02DestCurrencyCodeC(teesCodeDestino);
        currencyValue.setEesm02PlantCodeC(plant);
        try {
        		ret = dao.findCurrencyValues(currencyValue, fecha);
        	} catch (PersistenceException e) {
        			log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "Find Currencies Exception", e);
        	  throw new FullEconomicsException(e,FullEconomicsPrs.MessageErrors.CurrencyValues.FINDALL);
        	}
      log.exiting(CLASS_NAME, METHOD_NAME);
return ret;
}

    
    public BigDecimal getCurrentConvertRateByDate(Teesm01Currency orig,
    										Teesm01Currency dest,
    										Teesg01Plant plant,
    										Timestamp fecha )	throws FullEconomicsException {

    	
    	Collection<Teesm02Currvalue> currValueColl = findCurrencieValues(plant,fecha,orig,dest);

    	if (currValueColl.size() > 1 || currValueColl.isEmpty()) {
    		/* >1 cuando hay mas de un tipo de cambio */
    		String exchangeRate = "de " + orig.getEesm01CurrencyCodeC() + " a " + dest.getEesm01CurrencyCodeC() + " para la fecha: " + fecha.toString();
    		throw new FullEconomicsException(
    				new Exception(),FullEconomicsPrs.MessageErrors.CurrencyValues.FIND_CONVERT_RATE,exchangeRate);
    	}
    	return currValueColl.iterator().next().getEesm02ConvertRateAmountA();
    }

    
    
    
    public BigDecimal getCurrentConvertRate(Teesm01Currency orig,
                                            Teesm01Currency dest,
                                            Teesg01Plant plant)
            throws FullEconomicsException {

        Collection<Teesm02Currvalue> currValueColl = this.findCurrencieValues(
                plant, null, orig.getEesm01CurrencyCodeC(), dest
                        .getEesm01CurrencyCodeC());
        if (currValueColl.size() > 1 || currValueColl.isEmpty()) {
        	String exchangeRate = "de " + orig.getEesm01CurrencyCodeC() + " a " + dest.getEesm01CurrencyCodeC();
            throw new FullEconomicsException(
                    new Exception(),
                    FullEconomicsPrs.MessageErrors.CurrencyValues.FIND_CONVERT_RATE);
        }
        return currValueColl.iterator().next().getEesm02ConvertRateAmountA();
    }

    /**
     * Da de alta el Currency value pasado por parametro, verifica si la fecha
     * de fin del registro anterior es mayor a la fecha de inicio del registro a
     * dar de alta, si es asi setea la fecha de fin del registro anterior a un
     * dia antes del inicio del nuevo registro.
     * 
     * @param currencyOrig
     * @param currencyDest
     * @param convertRate
     * @param fechaIn
     * @param currencyOrigfechaOut
     * @param user
     * Usuario que da de alta el Currency
     */
    public void createCurrencyValue(String currencyOrig, String currencyDest,
                                    String convertRate, String fechaIn,
                                    String fechaOut, FullEconomicsWslxUser user)
            throws FullEconomicsException {

        String METHOD_NAME = "createCurrencyValue";
        log.entering(CLASS_NAME, METHOD_NAME);
        try {
            // PersistenceUtil.getPersistenceManager().clearCache();
            PersistenceUtil.newTransaction();
            CurrencyValuesDao dao = new CurrencyValuesDao();
            CurrencyLogic currLogic = new CurrencyLogic();
            Teesm02Currvalue currencyValue = new Teesm02Currvalue();
            Teesm02Currvalue prevCurrValue = null;
            Teesm02Currvalue workingCopy = null;
            Teesm01Currency teesmCurrencyOrig = currLogic
                    .findCurrencyByCode(currencyOrig);
            Teesm01Currency teesmCurrencyDest = currLogic
                    .findCurrencyByCode(currencyDest);

            Calendar fechaCalendarIn = FullEconomicsDateUtil.format(fechaIn);
            Timestamp tsFechaIn = new Timestamp(fechaCalendarIn
                    .getTimeInMillis());
            Calendar fechaCalendarOut = FullEconomicsDateUtil.format(fechaOut);
            Timestamp tsFechaOut = new Timestamp(fechaCalendarOut
                    .getTimeInMillis());

            BigDecimal bgConvertRate = new BigDecimal(convertRate);
            // seteo los datos del tipo de cambio
            currencyValue.setEesm02PlantCodeC(user.getTeesg01Plant());
            currencyValue.setEesm02OrigCurrencyCodeC(teesmCurrencyOrig);
            currencyValue.setEesm02DestCurrencyCodeC(teesmCurrencyDest);
            currencyValue.setEesm02ConvertRateAmountA(bgConvertRate);
            currencyValue.setEesm02CurrencyValueDateY(tsFechaIn);
            currencyValue.setEesm02CurrencyValOutDateY(tsFechaOut);

            // seteo los datos referentes ala creaciond el objeto
            currencyValue.setEesm02CreateS(new Timestamp(System
                    .currentTimeMillis()));
            currencyValue.setEesm02LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            currencyValue.setEesm02CreateUserC(user.getId());
            currencyValue.setEesm02LastUpdtUserC(user.getId());

            // busco el tipo de cambio anterior al presente
            prevCurrValue = dao.getPrevCurrencyValue(currencyValue);
            if (prevCurrValue != null) {// si existe y es necesario cambio su
                // fecha de cierre
                if (prevCurrValue.getEesm02CurrencyValOutDateY().getTime() > currencyValue
                        .getEesm02CurrencyValueDateY().getTime()) {
                    workingCopy = dao.getCurrencyValueForUpdate(prevCurrValue);
                    Timestamp prevCurrValueFechaOut = FullEconomicsDateUtil
                            .fechaMas(currencyValue
                                    .getEesm02CurrencyValueDateY(), -1);
                    workingCopy
                            .setEesm02CurrencyValOutDateY(prevCurrValueFechaOut);
                }
            }
            // llamo al crear Currency Value del dao
            dao.createCurrencyValue(currencyValue);
            PersistenceUtil.commitTransaction();

        } catch (PersistenceException pe) {

            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "PersistenceException", pe);
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }

            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Currency Exception", pe);
            throw new FullEconomicsException(pe,
                    FullEconomicsPrs.MessageErrors.CurrencyValues.CREATE);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Reinserta el currency value pasado por parametro
     * 
     * @param currencyValue
     * Currency a reinsertar
     */
    public void reInsertCurrencyValue(Teesm02Currvalue currencyValue)
            throws FullEconomicsException {
        String METHOD_NAME = "reInsertCurrencyValue";
        log.entering(CLASS_NAME, METHOD_NAME);
        try {
            PersistenceUtil.getPersistenceManager().clearCache();
            PersistenceUtil.newTransaction();
            CurrencyValuesDao dao = new CurrencyValuesDao();
            dao.createCurrencyValue(currencyValue);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException pe) {

            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "PersistenceException", pe);
            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }

            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Currency Exception", pe);
            throw new FullEconomicsException(pe,
                    FullEconomicsPrs.MessageErrors.CurrencyValues.REINSERT);
        }
    }

    /**
     * Actualiza el Currency Value pasado por parametro
     * 
     * @param currencyOrig
     * Currency origen
     * @param currencyDest
     * Currency destino
     * @param convertRate
     * tasa de cambio
     * @param fechaIn
     * fecha de inicio del currency value
     * @param fechaOut
     * fecha de Fin del currency value
     * @param user
     * Usuario que actualiza el Currency value
     */
    public void updateCurrencyValue(String currencyOrig, String currencyDest,
                                    String convertRate, String fechaIn,
                                    String fechaOut, FullEconomicsWslxUser user)
            throws FullEconomicsException {

        String METHOD_NAME = "updateCurrencyValue";
        log.entering(CLASS_NAME, METHOD_NAME);

        CurrencyValuesDao dao = new CurrencyValuesDao();
        CurrencyLogic currLogic = new CurrencyLogic();

        Teesm02Currvalue workingCopy = null;
        Teesm02Currvalue currValueForUpdate = new Teesm02Currvalue();

        try {
            Calendar fechaCalendarIn = FullEconomicsDateUtil.format(fechaIn);
            Timestamp tsFechaIn = new Timestamp(fechaCalendarIn
                    .getTimeInMillis());
            Calendar fechaCalendarOut = FullEconomicsDateUtil.format(fechaOut);
            Timestamp tsFechaOut = new Timestamp(fechaCalendarOut
                    .getTimeInMillis());
            BigDecimal bgConvertRate = new BigDecimal(convertRate);

            currValueForUpdate.setEesm02PlantCodeC(user.getTeesg01Plant());
            currValueForUpdate.setEesm02CurrencyValueDateY(tsFechaIn);
            currValueForUpdate.setEesm02DestCurrencyCodeC(currLogic
                    .findCurrencyByCode(currencyDest));
            currValueForUpdate.setEesm02OrigCurrencyCodeC(currLogic
                    .findCurrencyByCode(currencyOrig));

            // comienso la transaccion de update
            PersistenceUtil.newTransaction();

            PersistenceUtil.getPersistenceManager().clearCache();

            workingCopy = dao.getCurrencyValueForUpdate(currValueForUpdate);
            workingCopy.setEesm02LastUpdtUserC(user.getId());
            workingCopy.setEesm02LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));

            // Campos modificados, in y out date y convertRate
            workingCopy.setEesm02CurrencyValOutDateY(tsFechaOut);
            workingCopy.setEesm02ConvertRateAmountA(bgConvertRate);

            PersistenceUtil.commitTransaction();

        } catch (PersistenceException pe) {

            try {
                PersistenceUtil.rollbackTransaction();
            } catch (PersistenceException rollbackEx) {
                rollbackEx.printStackTrace();
            }

            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Update Currency Exception", pe);
            throw new FullEconomicsException(pe,
                    FullEconomicsPrs.MessageErrors.CurrencyValues.UPDATE);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Elimina el currency Value pasado por parametro
     * 
     * @param currencyValue
     * currency Value a borrar
     * @param confirmMovePrevDate
     * confirmacion para mover la fecha cierre del registro anteriro al borrado
     * a la fecha de cierre del registro borrado
     * 
     * @return boolean devuelve true si se borro y false si no se borro
     */
    public boolean deleteCurrencyValue(Teesm02Currvalue currencyValue,
                                       String confirmMovePrevDate)
            throws FullEconomicsException {

        String METHOD_NAME = "deleteCurrencyValue";
        log.entering(CLASS_NAME, METHOD_NAME);
        boolean success = true;
        try {
            PersistenceUtil.newTransaction();

            CurrencyValuesDao dao = new CurrencyValuesDao();
            Teesm02Currvalue prevCurrValue = null;
            Teesm02Currvalue workingCopy = null;
            prevCurrValue = dao.getPrevCurrencyValue(currencyValue);
            if (prevCurrValue != null) {// si existe y es necesario cambio su
                // fecha de cierre
                if (confirmMovePrevDate.equals("true")) {
                    workingCopy = dao.getCurrencyValueForUpdate(prevCurrValue);
                    workingCopy.setEesm02CurrencyValOutDateY(currencyValue
                            .getEesm02CurrencyValOutDateY());
                } else {
                    success = false;
                }
            }
            if (success) {
                dao.deleteCurrencyValue(currencyValue);
                PersistenceUtil.commitTransaction();
            }

        } catch (PersistenceException pe) {

            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Currency Exception", pe);
            throw new FullEconomicsException(pe,
                    FullEconomicsPrs.MessageErrors.CurrencyValues.DELETE);

        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return success;
    }

}
